package org.dreamwork.jasmine2.compiler;

import org.dreamwork.jasmine2.compiler.gui.JasmineCompilerFrame;
import org.xml.sax.SAXException;

import javax.swing.*;
import java.io.*;

/**
 * Created by IntelliJ IDEA.
 * User: seth.yang
 * Date: 2010-4-12
 * Time: 18:46:15
 */
public class JasmineCompilerFacade {
    private String outdir;
    private String srcdir;
    private String archive;
    private boolean createArchive;
    private JasmineCompiler compiler = new JasmineCompiler ();

    private boolean isGUISupport () {
        try {
            JFrame frame = new JFrame ();
            frame.dispose ();
            return true;
        } catch (Exception ex) {
            return false;
        }
    }

    private void compileCLI () throws IOException, SAXException, InterruptedException {
        BufferedReader reader = new BufferedReader (new InputStreamReader (System.in));
        if (outdir == null) {
            System.out.print ("Please input output dir [" + System.getProperty ("java.io.tmpdir") + "]:");
            String line = reader.readLine ();
            if (line.trim ().length () == 0) outdir = System.getProperty ("java.io.tmpdir");
            else outdir = line.trim ();
        }

        File file = new File (outdir);
        if (!file.exists ()) {
            System.out.printf ("%s not exist, do you want compiler create it? [Y]:", file.getParentFile ().getAbsolutePath ());
            String line;
            boolean right;
            do {
                line = reader.readLine ().trim ();
                right = line.equalsIgnoreCase ("y") || line.equalsIgnoreCase ("yes") || line.equalsIgnoreCase ("N") || line.equalsIgnoreCase ("no");
                if (!right) {
                    System.out.println ();
                    System.out.printf ("you can input Y/N or Yes/No only%n");
                    System.out.printf ("%s not exist, do you want compiler create it? [Y]:", file.getParentFile ().getAbsolutePath ());
                }
            } while (!right);
        }

        if (srcdir == null) {
            System.out.print ("Please input source dir: ");
            String line;
            boolean done;
            do {
                line = reader.readLine ().trim ();
                file = new File (line);
                done = file.exists () && file.isDirectory ();
                if (!done) {
                    System.out.printf ("source dir [%s] not exists!%n", file.getAbsolutePath ());
                    System.out.print ("Please input source dir: ");
                }
            } while (!done);
            srcdir = line;
        }

        if (archive == null) {
            System.out.print ("Do you want create archive file? [Y] :");
            String line;
            boolean right;
            do {
                line = reader.readLine ().trim ();
                right = line.equalsIgnoreCase ("y") || line.equalsIgnoreCase ("yes") || line.equalsIgnoreCase ("N") || line.equalsIgnoreCase ("no");
                if (!right) {
                    System.out.println ();
                    System.out.printf ("you can input Y/N or Yes/No only%n");
                    System.out.print ("Do you want create archive file? [Y] :");
                }                                             
            } while (!right);

            if (line.equalsIgnoreCase ("y") || line.equalsIgnoreCase ("yes")) {
                System.out.printf ("Please input archive file name [%s/jasmine-gen.jar] :", outdir);
                line = reader.readLine ().trim ();
                if (line.length () == 0) archive = String.format ("%s/jasmine-gen.jar", outdir);
                else archive = line;
            }
        }

        compiler.setBaseDir (srcdir);
        compiler.setDistDir (outdir + "/classes");
        compiler.setSrcDir (outdir + "/src");
        compiler.compile ();

        if (archive != null)
            createArchive (archive, outdir);
    }

    public static void createArchive (String archive, String outdir) throws IOException, InterruptedException {
        if (archive == null) return;
        String javaHome = System.getProperty ("java.home");
        File jdkHome = new File (javaHome).getParentFile ();
        File jarCommand = new File (jdkHome, "bin/jar");
        if (!jarCommand.exists ()) jarCommand = new File (jdkHome, "bin/jar.exe");
        if (!jarCommand.exists ())
            throw new RuntimeException ("JDK HOME must be set!");

        String command = jarCommand.getAbsolutePath ();
        ProcessBuilder pd = new ProcessBuilder (command, "cvf", archive, "-C", outdir, ".");
        System.out.printf ("%s cvf %s %s%n", command, archive, outdir);
        Process p = pd.start ();
        final InputStream in = p.getInputStream (), er = p.getErrorStream ();
        new Thread (new Runner (in, System.out)).start ();
        new Thread (new Runner (er, System.err)).start ();
        p.waitFor ();
    }

    private static class Runner implements Runnable {
        private InputStream in;
        private OutputStream out;

        public Runner (InputStream in, OutputStream out) {
            this.in = in;
            this.out = out;
        }

        public void run () {
            byte[] buff = new byte[SIZE];
            int length;
            try {
                while ((length = in.read (buff)) != -1) out.write (buff, 0, length);
            } catch (IOException ex) {
                throw new RuntimeException (ex);
            }
        }
    }

    private static final int SIZE = 10240;

    private void compileGUI () throws IOException {
        JasmineCompilerFrame frame = new JasmineCompilerFrame (compiler);
        frame.setVisible (true);
    }

    public void compile () throws IOException, SAXException, InterruptedException {
        if (isGUISupport ()) {
            compileGUI ();
        } else {
            compileCLI ();
        }
    }

    public static void main (String[] args) throws Exception {
/*
        java.util.Properties props = System.getProperties ();
        for (Object o : props.keySet ()) {
            String key = (String) o;
            String value = props.getProperty (key);
            System.out.printf ("%s -> %s%n", key, value);
        }
*/
        JasmineCompilerFacade jcf = new JasmineCompilerFacade ();
/*
        jcf.outdir = "D:\\tmp\\jasmine-compiler\\222\\classes";
        jcf.archive = "d:/tmp/java-archive-test.jar";
        createArchive (jcf.archive, jcf.outdir);
*/
        jcf.compile ();
    }
}